#!/bin/bash

# 脚本名称: replace_files_in_dirs.sh
# 功能: 在指定目录结构下，替换文件 或 还原备份文件。
# 作者: 资深技术专家
# 日期: 2025-09-09
# 版本: 4.0 (支持还原 + 参数化目录结构 + 无交互 + 查看 + 确认)

###使用方法###
###目录层级  aa/bb*   只替换内容
#替换文件
#./replace_files_in_dirs.sh /tmp/prod.conf aa 'bb*' app.conf

# 还原被替换的文件
#./replace_files_in_dirs.sh -r aa 'bb*' app.conf

show_usage() {
    echo "Usage:"
    echo "  替换模式: $0 <new_file_path> <base_dir> <subdir_pattern> <target_filename>"
    echo "  还原模式: $0 -r <base_dir> <subdir_pattern> <target_filename>"
    echo ""
    echo "Example (替换):"
    echo "  $0 /tmp/new.conf aa 'bb*' app.conf"
    echo ""
    echo "Example (还原):"
    echo "  $0 -r aa 'bb*' app.conf"
    echo ""
    echo "说明:"
    echo "  -r, --restore : 启用还原模式，将 .bak 备份文件恢复为原文件。"
    echo "  <new_file_path>: (仅替换模式) 新文件的完整路径"
    echo "  <base_dir>    : 基础目录（如 'aa'）"
    echo "  <subdir_pattern>: 子目录匹配模式（如 'bb*'，支持通配符）"
    echo "  <target_filename>: 文件名（替换模式下为目标文件；还原模式下为要还原的文件名）"
}

# === 解析还原选项 ===
RESTORE_MODE=false
while [[ $# -gt 0 ]]; do
    case $1 in
        -r|--restore)
            RESTORE_MODE=true
            shift
            ;;
        *)
            break
            ;;
    esac
done

# === 参数校验 ===
if [ "$RESTORE_MODE" = true ]; then
    if [ $# -ne 3 ]; then
        echo "❌ 错误：还原模式下需要 3 个参数。"
        show_usage
        exit 1
    fi
    BASE_DIR="$1"
    SUBDIR_PATTERN="$2"
    TARGET_FILENAME="$3"
else
    if [ $# -ne 4 ]; then
        echo "❌ 错误：替换模式下需要 4 个参数。"
        show_usage
        exit 1
    fi
    NEW_FILE="$1"
    BASE_DIR="$2"
    SUBDIR_PATTERN="$3"
    TARGET_FILENAME="$4"

    # 校验新文件
    if [ ! -f "$NEW_FILE" ]; then
        echo "❌ 错误：新文件 '$NEW_FILE' 不存在或不是普通文件。"
        exit 1
    fi
fi

# 校验基础目录
if [ ! -d "$BASE_DIR" ]; then
    echo "❌ 错误：基础目录 '$BASE_DIR' 不存在或不是目录。"
    exit 1
fi

# === 根据模式执行不同操作 ===
if [ "$RESTORE_MODE" = true ]; then
    echo "🔄【还原模式】即将还原文件: $TARGET_FILENAME"
else
    echo "📥【替换模式】即将用文件 '$NEW_FILE' 替换目标文件。"
    # 打印新文件信息
    echo "========================================"
    echo "【新文件信息】"
    ls -l "$NEW_FILE"
    echo "内容预览 (前5行):"
    head -n 5 "$NEW_FILE"
    MD5_NEW=$(md5sum "$NEW_FILE" | awk '{print $1}')
    echo "MD5 校验码: $MD5_NEW"
fi

echo "========================================"
echo "【操作概览】"
echo "  模式:           $([ "$RESTORE_MODE" = true ] && echo "还原" || echo "替换")"
echo "  基础目录:       $BASE_DIR"
echo "  子目录模式:     $SUBDIR_PATTERN"
echo "  目标文件名:     $TARGET_FILENAME"
[ "$RESTORE_MODE" = false ] && echo "  新文件路径:     $NEW_FILE"
echo "========================================"

# === 查找匹配的子目录 ===
shopt -s nullglob
SUBDIRS=("$BASE_DIR"/$SUBDIR_PATTERN)

if [ ${#SUBDIRS[@]} -eq 0 ]; then
    echo "⚠️  警告：未找到匹配子目录 '$SUBDIR_PATTERN' 在 '$BASE_DIR' 下。"
    exit 0
fi

# === 核心处理循环 ===
for dir in "${SUBDIRS[@]}"; do
    if [ ! -d "$dir" ]; then
        continue
    fi

    TARGET_FILE="$dir/$TARGET_FILENAME"
    BACKUP_FILE="$TARGET_FILE.bak"

    if [ "$RESTORE_MODE" = true ]; then
        # ========== 还原模式 ==========
        if [ -f "$BACKUP_FILE" ]; then
            echo -e "\n>>> 还原文件: $TARGET_FILE"

            # --- 查看项：还原前 ---
            echo "【还原前 - 当前文件信息】"
            if [ -f "$TARGET_FILE" ]; then
                ls -l "$TARGET_FILE"
                echo "当前内容预览 (前3行):"
                head -n 3 "$TARGET_FILE"
                MD5_CURRENT=$(md5sum "$TARGET_FILE" | awk '{print $1}')
                echo "当前 MD5: $MD5_CURRENT"
            else
                echo "  [INFO] 目标文件不存在，将从备份创建。"
            fi

            echo "【执行还原】"
            cp "$BACKUP_FILE" "$TARGET_FILE" && {
                echo "  ✅ 还原成功。"
                # 删除备份文件（可选）
                # rm "$BACKUP_FILE" && echo "  🗑️  备份文件已删除。"

                # --- 修改确认项：还原后 ---
                echo "【还原后 - 当前文件信息】"
                ls -l "$TARGET_FILE"
                echo "当前内容预览 (前3行):"
                head -n 3 "$TARGET_FILE"
                MD5_RESTORED=$(md5sum "$TARGET_FILE" | awk '{print $1}')
                MD5_BACKUP=$(md5sum "$BACKUP_FILE" | awk '{print $1}')
                echo "还原后 MD5: $MD5_RESTORED"
                echo "备份文件 MD5: $MD5_BACKUP"

                if [ "$MD5_RESTORED" = "$MD5_BACKUP" ]; then
                    echo "  ✅ [SUCCESS] 还原操作已确认完成，内容与备份一致。"
                else
                    echo "  ❌ [ERROR] 还原后内容与备份不一致！"
                fi
            } || {
                echo "  ❌ [ERROR] 还原失败。"
            }
        else
            echo "  ⚠️  [WARNING] 在目录 $dir 中未找到备份文件: $BACKUP_FILE"
        fi

    else
        # ========== 替换模式 ==========
        if [ -f "$TARGET_FILE" ]; then
            echo -e "\n>>> 处理文件: $TARGET_FILE"

            # --- 查看项：替换前 ---
            echo "【替换前 - 原文件信息】"
            ls -l "$TARGET_FILE"
            echo "原内容预览 (前5行):"
            head -n 5 "$TARGET_FILE"
            MD5_OLD=$(md5sum "$TARGET_FILE" | awk '{print $1}')
            echo "原文件 MD5: $MD5_OLD"

            # 创建备份
            echo "【执行备份】"
            cp "$TARGET_FILE" "$BACKUP_FILE" && echo "  ✅ 备份成功: $BACKUP_FILE" || {
                echo "  ❌ [ERROR] 备份失败！跳过此文件。"
                continue
            }

            # 执行替换
            echo "【执行替换】"
            cp "$NEW_FILE" "$TARGET_FILE"
            if [ $? -eq 0 ]; then
                echo "  ✅ 文件复制成功。"

                # --- 修改确认项：替换后 ---
                echo "【替换后 - 当前文件信息】"
                ls -l "$TARGET_FILE"
                echo "当前内容预览 (前5行):"
                head -n 5 "$TARGET_FILE"
                MD5_CURRENT=$(md5sum "$TARGET_FILE" | awk '{print $1}')
                echo "当前文件 MD5: $MD5_CURRENT"

                if [ "$MD5_NEW" = "$MD5_CURRENT" ]; then
                    echo "  ✅ [SUCCESS] 文件替换已确认完成，内容与源文件一致。"
                else
                    echo "  ❌ [ERROR] 文件内容与源文件不一致！请立即检查！"
                fi
            else
                echo "  ❌ [ERROR] 文件复制失败。请检查权限或磁盘空间。"
            fi

        else
            echo "  ⚠️  [WARNING] 在目录 $dir 中未找到文件: $TARGET_FILENAME"
        fi
    fi
done

echo -e "\n✅ 所有操作已完成。"
